package mashibing.freshman.class04;

// LeetCode测试链接：https://leetcode.com/problems/reverse-nodes-in-k-group/
/** 25题.K 个一组翻转链表  难度：hard
 * 给定一个单链表的头节点head，和一个正数k
 * 实现k个节点的小组内部逆序，如果最后一组不够k个就不调整
 * 例子:
 * 调整前：1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8，k = 3
 * 调整后：3 -> 2 -> 1 -> 6 -> 5 -> 4 -> 7 -> 8
 */
public class Code04_ReverseNodesInKGroup {
	// 不要提交这个类
	public static class ListNode {
		public int val;
		public ListNode next;
	}

	public static ListNode reverseKGroup(ListNode head, int k) {
		ListNode start = head;
		ListNode end = getKGroupEnd(start, k);
		if (end == null) {// 边界值：end到null就结束
			return head;
		}
		// 第一组凑齐了！
		head = end;//head抓住新头部，以后就不动了
		reverse(start, end);
		// 上一组的结尾节点
		ListNode lastEnd = start;
		while (lastEnd.next != null) {
			start = lastEnd.next;
			end = getKGroupEnd(start, k);
			if (end == null) {
				return head;
			}
			reverse(start, end);
			lastEnd.next = end;
			lastEnd = start;
		}
		return head;
	}
	// abcdf
	// 返回从这个节点开始的第k个数，假设k =4
	// 获取 d节点
	// 入参a，4
	public static ListNode getKGroupEnd(ListNode start, int k) {
		while (--k != 0 && start != null) {// 已经考虑边界值了：不够k个数，返回空
			start = start.next;
		}
		return start;
	}
	// 反转
	// abcdf —— dcbaf
	// 入参，a,d
	public static void reverse(ListNode start, ListNode end) {
		end = end.next;
		ListNode pre = null;
		ListNode cur = start;
		ListNode next = null;
		while (cur != end) {
			next = cur.next;
			cur.next = pre;
			pre = cur;
			cur = next;
		}
		start.next = end;
	}

}
